package main

import (
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/tealeg/xlsx"
)

// OrderRecord 表示订单记录的结构体
type OrderRecord struct {
	BusinessOrderNumber string
	BusinessDate        string
	BelongTo            string
	PayAmount           string
}

// DifferenceRecord 表示差异记录的结构体
type DifferenceRecord struct {
	AccountOrderNumber  string
	AccountDate         string
	AccountBelongTo     string
	AccountPayAmount    string
	PaymentOrderNumber  string
	PaymentDate         string
	PaymentOutletNumber string
	PaymentPayAmount    string
	DifferenceReason    string
}

// normalizeOrderNumber 将业务订单号转换为纯数字字符串
func normalizeOrderNumber(orderNumber string) string {
	return strings.Map(func(r rune) rune {
		if '0' <= r && r <= '9' {
			return r
		}
		return -1
	}, orderNumber)
}

// normalizeDate 函数将字符串类型的日期转换成 time.Time 类型
func normalizeDate(dateString string) (time.Time, error) {
	layout := "2006-01-02"
	return time.Parse(layout, strings.Replace(dateString, "\\", "", -1))
}

// ReadExcel 读取Excel文件到记录切片中
func ReadExcel(filename, sheetName string, fileType string) ([]OrderRecord, error) {
	f, err := xlsx.OpenFile(filename)
	if err != nil {
		return nil, err
	}
	sheet, ok := f.Sheet[sheetName]
	if !ok {
		return nil, fmt.Errorf("找不到 %s", sheetName)
	}

	// 读取列标题
	headers := sheet.Rows[0].Cells
	columns := make(map[string]int)
	for i, cell := range headers {
		columns[cell.String()] = i
	}

	var records []OrderRecord
	for _, row := range sheet.Rows[1:] {
		record := OrderRecord{}
		for columnName, colIndex := range columns {
			cell := row.Cells[colIndex]
			if cell != nil {
				text := strings.TrimSpace(cell.String()) // 去除单元格内容的首尾空格
				if fileType == "account" {
					switch columnName {
					case "业务订单号":
						record.BusinessOrderNumber = normalizeOrderNumber(text)
					case "归属地":
						record.BelongTo = text
					case "充值金额":
						record.PayAmount = text
					case "业务日":
						// 尝试将文本转换为日期，并格式化为 "2006-01-02" 格式
						date, err := normalizeDate(text)
						if err != nil {
							// 如果日期解析失败，保持原始文本不变
							date = time.Time{}
						}
						record.BusinessDate = date.Format("2006-01-02")
					}
				} else if fileType == "payment" {
					switch columnName {
					case "业务订单号":
						record.BusinessOrderNumber = normalizeOrderNumber(text)
					case "网点编号":
						record.BelongTo = text
					case "支付金额":
						record.PayAmount = text
					case "营业日":
						// 尝试将文本转换为日期，并格式化为 "2006-01-02" 格式
						date, err := normalizeDate(text)
						if err != nil {
							// 如果日期解析失败，保持原始文本不变
							date = time.Time{}
						}
						// 根据列名设置相应的日期字段
						record.BusinessDate = date.Format("2006-01-02")
					}
				}
			}
		}
		records = append(records, record)
	}

	return records, nil
}

// WriteDifferences 将差异写入Excel文件
func WriteDifferences(filename string, differences []DifferenceRecord) error {
	f := xlsx.NewFile()
	sheet, err := f.AddSheet("差异记录")
	if err != nil {
		return err
	}

	// 添加标题行
	row := sheet.AddRow()
	cell := row.AddCell()
	cell.Value = "账户中心订单号"
	cell = row.AddCell()
	cell.Value = "账户中心业务日"
	cell = row.AddCell()
	cell.Value = "账户中心归属地"
	cell = row.AddCell()
	cell.Value = "账户中心充值金额"
	cell = row.AddCell()
	cell.Value = "支付中心订单号"
	cell = row.AddCell()
	cell.Value = "支付中心营业日"
	cell = row.AddCell()
	cell.Value = "支付中心网点编号"
	cell = row.AddCell()
	cell.Value = "支付中心充值金额"
	cell = row.AddCell()
	cell.Value = "差异原因"

	// 添加差异记录
	for _, diff := range differences {
		row := sheet.AddRow()
		cell := row.AddCell()
		cell.Value = diff.AccountOrderNumber
		cell = row.AddCell()
		cell.Value = diff.AccountDate
		cell = row.AddCell()
		cell.Value = diff.AccountBelongTo
		cell = row.AddCell()
		cell.Value = diff.AccountPayAmount
		cell = row.AddCell()
		if diff.PaymentOrderNumber != "" {
			cell.Value = diff.PaymentOrderNumber
		}
		cell = row.AddCell()
		if diff.PaymentDate != "" {
			cell.Value = diff.PaymentDate
		}
		cell = row.AddCell()
		if diff.PaymentOutletNumber != "" {
			cell.Value = diff.PaymentOutletNumber
		}
		cell = row.AddCell()
		cell.Value = diff.PaymentPayAmount
		cell = row.AddCell()
		cell.Value = diff.DifferenceReason
	}

	if err := f.Save(filename); err != nil {
		return err
	}

	return nil
}

// CompareOrders 函数用于比较两个订单记录数组，返回差异记录数组
// ordersAccount: 账户中心订单记录数组
// ordersPayment: 支付中心订单记录数组
// 返回差异记录数组
func CompareOrders(ordersAccount, ordersPayment []OrderRecord, correctRecords *[]OrderRecord) []DifferenceRecord {
	var differences []DifferenceRecord
	orderPaymentMap := make(map[string]OrderRecord)

	for _, order := range ordersPayment {
		orderPaymentMap[normalizeOrderNumber(order.BusinessOrderNumber)] = order
	}

	for _, accountOrder := range ordersAccount {
		paymentOrder, exists := orderPaymentMap[normalizeOrderNumber(accountOrder.BusinessOrderNumber)]
		if !exists {
			// 账户中心存在但支付中心不存在的订单
			differences = append(differences, DifferenceRecord{
				AccountOrderNumber: normalizeOrderNumber(accountOrder.BusinessOrderNumber),
				AccountDate:        accountOrder.BusinessDate,
				AccountBelongTo:    accountOrder.BelongTo,
				AccountPayAmount:   accountOrder.PayAmount,
				DifferenceReason:   "支付中心不存在该业务订单号",
			})
			continue
		}

		// 订单存在但业务日和营业日不一致
		if accountOrder.BusinessDate != paymentOrder.BusinessDate {
			differences = append(differences, DifferenceRecord{
				AccountOrderNumber:  normalizeOrderNumber(accountOrder.BusinessOrderNumber),
				AccountDate:         accountOrder.BusinessDate,
				AccountBelongTo:     accountOrder.BelongTo,
				AccountPayAmount:    accountOrder.PayAmount,
				PaymentOrderNumber:  normalizeOrderNumber(paymentOrder.BusinessOrderNumber),
				PaymentDate:         paymentOrder.BusinessDate,
				PaymentOutletNumber: paymentOrder.BelongTo,
				PaymentPayAmount:    paymentOrder.PayAmount,
				DifferenceReason:    "业务日与营业日不一致",
			})
		}

		// 订单存在但归属地不一致
		if accountOrder.BelongTo != paymentOrder.BelongTo {
			differences = append(differences, DifferenceRecord{
				AccountOrderNumber:  normalizeOrderNumber(accountOrder.BusinessOrderNumber),
				AccountDate:         accountOrder.BusinessDate,
				AccountBelongTo:     accountOrder.BelongTo,
				AccountPayAmount:    accountOrder.PayAmount,
				PaymentOrderNumber:  normalizeOrderNumber(paymentOrder.BusinessOrderNumber),
				PaymentDate:         paymentOrder.BusinessDate,
				PaymentOutletNumber: paymentOrder.BelongTo,
				PaymentPayAmount:    paymentOrder.PayAmount,
				DifferenceReason:    "归属地与网点编号不一致",
			})
		}

		// 订单存在但归属地不一致
		if accountOrder.PayAmount != paymentOrder.PayAmount {
			differences = append(differences, DifferenceRecord{
				AccountOrderNumber:  normalizeOrderNumber(accountOrder.BusinessOrderNumber),
				AccountDate:         accountOrder.BusinessDate,
				AccountBelongTo:     accountOrder.BelongTo,
				AccountPayAmount:    accountOrder.PayAmount,
				PaymentOrderNumber:  normalizeOrderNumber(paymentOrder.BusinessOrderNumber),
				PaymentDate:         paymentOrder.BusinessDate,
				PaymentOutletNumber: paymentOrder.BelongTo,
				PaymentPayAmount:    paymentOrder.PayAmount,
				DifferenceReason:    "充值金额不一致",
			})
		}
	}

	// 收集核对无误的记录
	for _, accountOrder := range ordersAccount {
		_, exists := orderPaymentMap[normalizeOrderNumber(accountOrder.BusinessOrderNumber)]
		if exists {
			*correctRecords = append(*correctRecords, accountOrder)
		}
	}

	return differences
}

// WriteCorrectRecords 将正确订单记录写入Excel文件
func WriteCorrectRecords(filename string, correctRecords []OrderRecord) error {
	f := xlsx.NewFile()
	sheet, err := f.AddSheet("正确记录")
	if err != nil {
		return err
	}

	// 添加标题行
	row := sheet.AddRow()
	cell := row.AddCell()
	cell.Value = "订单号"
	cell = row.AddCell()
	cell.Value = "业务日"
	cell = row.AddCell()
	cell.Value = "归属地"
	cell = row.AddCell()
	cell.Value = "充值金额"

	// 添加正确记录
	for _, record := range correctRecords {
		row := sheet.AddRow()
		cell := row.AddCell()
		cell.Value = record.BusinessOrderNumber
		cell = row.AddCell()
		cell.Value = record.BusinessDate
		cell = row.AddCell()
		cell.Value = record.BelongTo
		cell = row.AddCell()
		cell.Value = record.PayAmount
	}

	if err := f.Save(filename); err != nil {
		return err
	}

	return nil
}

func main() {
	// 读取两个Excel文件
	ordersAccount, err := ReadExcel("input/账户中心充值订单明细查询.xlsx", "Sheet1", "account")
	if err != nil {
		log.Fatal("读取账户中心Excel出错:", err)
	}
	ordersPayment, err := ReadExcel("input/支付中心充值订单明细查询.xlsx", "Sheet1", "payment")
	if err != nil {
		log.Fatal("读取支付中心Excel出错:", err)
	}
	// 打印
	// if ordersAccount != nil {
	// 	fmt.Printf("账户中心订单: %v\n", ordersAccount)
	// }
	// if ordersPayment != nil {
	// 	fmt.Printf("支付中心订单: %v\n", ordersPayment)
	// }

	// 比较差异并准备差异记录
	var correctRecords []OrderRecord // 用于收集核对无误的记录
	differences := CompareOrders(ordersAccount, ordersPayment, &correctRecords)

	// 输出差异到Excel文件
	outputPath := "output/差异记录.xlsx"
	err = WriteDifferences(outputPath, differences)
	if err != nil {
		log.Fatal("写入差异记录Excel出错:", err)
	}
	fmt.Printf("差异记录已写入到 %s\n", outputPath)

	// 输出核对无误的记录到Excel文件
	correctOutputPath := "output/正确记录.xlsx"
	err = WriteCorrectRecords(correctOutputPath, correctRecords)
	if err != nil {
		log.Fatal("写入正确记录Excel出错:", err)
	}
	fmt.Printf("正确记录已写入到 %s\n", correctOutputPath)
}
